<template xlang="wxml">
	<view class="rider-tree">
		<view class="rider-tree-mask" :class="{ show: showTree }" @tap="_cancel"></view>
		<view class="rider-tree-cnt" :class="{ show: showTree }">
			<view class="rider-tree-bar">
				<view class="rider-tree-bar-cancel" :style="{ color: cancelColor }" hover-class="hover-c" @tap="_cancel">取消</view>
				<view class="rider-tree-bar-title" :style="{ color: titleColor }">{{ title }}</view>
				<view class="rider-tree-bar-confirm" :style="{ color: confirmColor }" hover-class="hover-c" @tap="_confirm">确定</view>
			</view>
			<view class="rider-tree-view">
				<scroll-view class="rider-tree-view-sc" :scroll-y="true">
					<block v-for="(item, index) in treeList" :key="index">
						<view
							class="rider-tree-item"
							:style="[{ paddingLeft: item.rank * 15 + 'px', zIndex: item.rank * -1 + 50 }]"
							:class="{ show: item.show, last: item.lastRank, showchild: item.showChild, open: item.open }"
						>
							<view class="rider-tree-label" @tap.stop="onTreeItemTap(item, index)">
								<image
									class="rider-tree-icon"
									:src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon"
								></image>
								{{ item.name }}
							</view>
							<view class="rider-tree-check" @tap.stop="onTreeItemSelect(item, index)" v-if="selectParent ? true : item.lastRank">
								<view
									class="rider-tree-check-yes"
									v-if="item.checked"
									:class="{ radio: !multiple }"
									:style="{ 'border-color': confirmColor }"
								>
									<view class="rider-tree-check-yes-b" :style="{ 'background-color': confirmColor }"></view>
								</view>
								<view
									class="rider-tree-check-no"
									v-else
									:class="{ radio: !multiple }"
									:style="{ 'border-color': confirmColor }"
								></view>
							</view>
						</view>
					</block>
				</scroll-view>
			</view>
		</view>
	</view>
</template>

<script>
export default {
	name: 'rider-tree',
	props: {
		range: {
			type: Array,
			default: function() {
				return []
			}
		},
		idKey: {
			//字段key值
			type: String,
			default: 'id'
		},
		nameKey: {
			//字段value值
			type: String,
			default: 'name'
		},
		allKey: {
			//冗余字段
			type: String,
			default: 'value'
		},
		title: {
			//头
			type: String,
			default: ''
		},
		multiple: {
			// 是否可以多选
			type: Boolean,
			default: true
			// default: true
		},
		cascade: {
			// 是否级联选择
			type: Boolean,
			default: false
			// default: true
		},
		selectParent: {
			//是否可以选父级
			type: Boolean,
			default: true
		},
		foldAll: {
			//折叠时关闭所有已经打开的子集，再次打开时需要一级一级打开
			type: Boolean,
			default: false
		},
		confirmColor: {
			// 确定按钮颜色
			type: String,
			default: '' // #007aff
		},
		cancelColor: {
			// 取消按钮颜色
			type: String,
			default: '' // #757575
		},
		titleColor: {
			// 标题颜色
			type: String,
			default: '' // #757575
		},
		currentIcon: {
			// 展开时候的ic
			type: String,
			default:
				''
		},
		defaultIcon: {
			// 折叠时候的ic
			type: String,
			default:
				''
		},
		lastIcon: {
			// 没有子集的ic
			type: String,
			default: ''
		}
	},
	data() {
		return {
			showTree: false,
			treeList: [],
			selectIndex: -1,
			returnedItem: [], //定义一个空数组
			pids: [],
			ancestorsIds: [],
			childNums: []
		}
	},
	computed: {},
	methods: {
		_show() {
			this.showTree = true
		},
		_hide() {
			this.showTree = false
		},
		_cancel() {
			this._hide()
			this.$emit('cancel', [])
		},
		_confirm() {
			// 处理所选数据
			let rt = [],
				obj = {}
			this.treeList.forEach((v, i) => {
				if (this.treeList[i].checked) {
					rt.push({
						id: this.treeList[i].id,
						name: this.treeList[i].name,
						value: this.treeList[i].value
					})
				}
			})
			this._hide()
			this.$emit('confirm', rt)
		},
		//扁平化树结构
		_renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
			list.forEach(item => {
				this.treeList.push({
					id: item[this.idKey],
					name: item[this.nameKey],
					value: item[this.allKey],
					source: item,
					parentId, // 父级id数组
					parents, // 父级id数组
					rank, // 层级
					showChild: false, //子级是否显示
					open: false, //是否打开
					show: rank === 0, // 自身是否显示
					hideArr: [],
					orChecked: item.checked ? item.checked : false,
					checked: item.checked ? item.checked : false,
					childNum: 0
				})

				if (Array.isArray(item.children) && item.children.length > 0) {
					// console.log(item)
					let parentid = [...parentId],
						parentArr = [...parents]
					delete parentArr.children
					parentid.push(item[this.idKey])
					parentArr.push({
						[this.idKey]: item[this.idKey],
						[this.nameKey]: item[this.nameKey],
						[this.allKey]: item[this.allKey]
					})
					this._renderTreeList(item.children, rank + 1, parentid, parentArr)
				} else {
					this.treeList[this.treeList.length - 1].lastRank = true
				}
			})
		},
		// 处理默认选择
		_defaultSelect() {
			this.treeList.forEach((v, i) => {
				if (v.checked) {
					this.treeList.forEach((v2, i2) => {
						if (v.parentId.toString().indexOf(v2.parentId.toString()) >= 0) {
							v2.show = true
							if (v.parentId.includes(v2.id)) {
								v2.showChild = true
								v2.open = true
							}
						}
					})
				}
			})
		},
		getOwn(id, arr) {
			//利用foreach循环遍历
			arr.forEach(item => {
				//判断递归结束条件
				if (item[this.idKey] == id) {
					// 存储数据到空数组
					this.returnedItem = item
				} else if (item.children != null) {
					//判断chlidren是否有数据
					//递归调用
					this.getOwn(id, item.children)
				}
			})
			return this.returnedItem
		},
		setShow(id, arr, isShow) {
			arr.forEach((item, index) => {
				if (item.parentId.includes(id)) {
					this.treeList[index].showChild = isShow
					this.treeList[index].show = isShow
				} else if (item.children !== undefined) {
					this.setShow(id, item.children, isShow)
				}
			})
		},
		// 点击
		onTreeItemTap(item, index) {
			// console.log(item)
			if (item.lastRank === true) {
				//点击最后一级时触发事件
				this.treeList[index].checked = !this.treeList[index].checked
				this._fixMultiple(index)
				return
			}
			let id = item.id
			item.showChild = !item.showChild
			// qingqian
			if (item.showChild) {
				const range = this.range
				const parentIdArr = item.parentId
				// 找到当前元素
				const own = this.getOwn(id, range)
				const checkedChildren = own.children
				// 子元素插入的索引位置
				const nextIndex = this.treeList.findIndex(itemT => itemT.id === item.id)
				if (checkedChildren === undefined || checkedChildren.length < 1) {
					return
				}
				// 子节点数量
				this.treeList[index].childNum = checkedChildren.length
				const newRank = item.rank + 1
				checkedChildren.forEach(itemC => {
					const childObj = {
						id: itemC[this.idKey],
						name: itemC[this.nameKey],
						value: itemC[this.allKey],
						source: {},
						parentId: [item.id], // 父级id数组
						parents: [item], // 父级id数组
						rank: newRank, // 层级
						showChild: false, //子级是否显示
						open: false, //是否打开
						show: 1, // 自身是否显示
						hideArr: [],
						lastRank: itemC.children && itemC.children.length > 0 ? false : true,
						orChecked: this.treeList[index].checked,
						checked: this.cascade ? this.treeList[index].checked : false
					}
					if (!this.treeList.some(itemT => itemT.id === itemC[this.idKey])) {
						this.treeList.splice(nextIndex + 1, 0, childObj)
					}
				})
			}
			// 展开/隐藏子级/孙级
			let list = this.treeList
			item.open = item.showChild ? true : !item.open
			list.forEach((childItem, i) => {
				if (item.showChild === false) {
					//隐藏所有子级
					if (!childItem.parentId.includes(id)) {
						return
					}
					//TODO: 修改
					if (!this.foldAll) {
						if (childItem.lastRank !== true && !childItem.open) {
							childItem.showChild = false
							this.setShow(childItem.id, this.treeList, false)
						}
						// 为隐藏的内容添加一个标记
						if (childItem.show) {
							childItem.hideArr[item.rank] = id
						}
					} else {
						if (childItem.lastRank !== true) {
							childItem.showChild = false
							// 继续隐藏子级的的子级
							this.setShow(childItem.id, this.treeList, false)
						}
					}
					if (childItem.children !== undefined) {
						childItem.children.forEach((childItem1, i1) => {
							if (!childItem1.parentId.includes(childItem.id)) {
								return
							}
							childItem.children[i1].showChild = false
							childItem.children[i1].show = false
						})
					}
					childItem.show = false
				} else {
					// 打开子集
					if (childItem.parentId[childItem.parentId.length - 1] === id) {
						childItem.show = true
					}
					// 打开被隐藏的子集
					if (childItem.parentId.includes(id) && !this.foldAll) {
						// console.log(childItem.hideArr)
						if (childItem.hideArr[item.rank] === id) {
							childItem.show = true
							if (childItem.open && childItem.showChild) {
								childItem.showChild = true
							} else {
								childItem.showChild = false
							}
							childItem.hideArr[item.rank] = null
						}
					}
				}
			})
		},
		// 通过父id处理子级
		syncChecked(trees, pid, checked) {
			trees.forEach((item, index) => {
				if (item.parentId.includes(pid)) {
					this.treeList[index].checked = checked
					this.syncChecked(trees, item.id, checked)
				} else if (item.children !== undefined) {
					this.syncChecked(item.children, pid, checked)
				}
			})
		},
		// 获取父级往上所有层级的id 并同步状态
		setAncestors(pids, checked) {
			this.treeList.forEach((item, index) => {
				if (pids.includes(item.id)) {
					if (checked && this.childNums[item.id] !== undefined && item.childNum === this.childNums[item.id]) {
						// 子级全部选中, 父级才选中
						this.treeList[index].checked = true
					} else {
						this.treeList[index].checked = false
					}
					this.setAncestors(item.parentId, checked)
				}
			})
		},
		onTreeItemSelect(item, index) {
			this.treeList[index].checked = !this.treeList[index].checked
			// 选父级, 子级自动全选
			if (this.cascade) {
				this.syncChecked(this.treeList, item.id, this.treeList[index].checked)
			}

			if (item.rank > 0) {
				item.parentId.forEach((pid, indexP) => {
					const parent = this.treeList.filter(i => i.id === pid)
					const childNum = parent.length > 0 ? parent[0].childNum : 0
					if (this.childNums[pid] === undefined) {
						this.childNums[pid] = 1
					} else if (this.childNums[pid] < childNum) {
						this.childNums[pid]++
					}
				})
				//子级选择/选满/取消选择, 父级往上同步状态
				if (this.cascade) {
					this.setAncestors(item.parentId, this.treeList[index].checked)
				}
			}
			this._fixMultiple(index)
		},
		// 处理单选多选
		_fixMultiple(index) {
			if (!this.multiple) {
				// 如果是单选
				this.treeList.forEach((v, i) => {
					if (i != index) {
						this.treeList[i].checked = false
					} else {
						this.treeList[i].checked = true
					}
				})
			}
		},
		// 重置数据
		_reTreeList() {
			this.treeList.forEach((v, i) => {
				this.treeList[i].checked = v.orChecked
			})
		},
		_initTree(range = this.range) {
			this.treeList = []
			this._renderTreeList(range)
			this.$nextTick(() => {
				this._defaultSelect(range)
			})
		}
	},
	watch: {
		range(list) {
			this._initTree(list)
		},
		multiple() {
			if (this.range.length) {
				this._reTreeList()
			}
		},
		selectParent() {
			if (this.range.length) {
				this._reTreeList()
			}
		}
	},
	mounted() {
		this._initTree()
	}
}
</script>

<style scoped>
.rider-tree-mask {
	position: fixed;
	top: 0rpx;
	right: 0rpx;
	bottom: 0rpx;
	left: 0rpx;
	z-index: 9998;
	background-color: rgba(0, 0, 0, 0.6);
	opacity: 0;
	transition: all 0.3s ease;
	visibility: hidden;
}

.rider-tree-mask.show {
	visibility: visible;
	opacity: 1;
}

.rider-tree-cnt {
	position: fixed;
	top: 0rpx;
	right: 0rpx;
	bottom: 0rpx;
	left: 0rpx;
	z-index: 19999;
	top: 15vh;
	transition: all 0.3s ease;
	transform: translateY(100%);
}

.rider-tree-cnt.show {
	transform: translateY(0);
}

.rider-tree-bar {
	background-color: #fff;
	height: 72rpx;
	padding-left: 20rpx;
	padding-right: 20rpx;
	display: flex;
	justify-content: space-between;
	align-items: center;
	box-sizing: border-box;
	border-bottom-width: 1rpx !important;
	border-bottom-style: solid;
	border-bottom-color: #f5f5f5;
	font-size: 32rpx;
	color: #757575;
	line-height: 1;
}

.rider-tree-bar-confirm {
	color: #007aff;
}

.rider-tree-view {
	position: absolute;
	top: 0rpx;
	right: 0rpx;
	bottom: 0rpx;
	left: 0rpx;
	top: 72rpx;
	background-color: #fff;
	padding-top: 20rpx;
	padding-right: 20rpx;
	padding-bottom: 20rpx;
	padding-left: 20rpx;
}

.rider-tree-view-sc {
	height: 100%;
	overflow: hidden;
}

.rider-tree-item {
	display: flex;
	justify-content: space-between;
	align-items: center;
	font-size: 26rpx;
	color: #757575;
	line-height: 1;
	height: 0;
	opacity: 0;
	transition: 0.2s;
	position: relative;
	overflow: hidden;
}

.rider-tree-item.show {
	height: 80rpx;
	opacity: 1;
}

.rider-tree-item.showchild:before {
	transform: rotate(90deg);
}

.rider-tree-item.last:before {
	opacity: 0;
}

.rider-tree-icon {
	width: 26rpx;
	height: 26rpx;
	margin-right: 8rpx;
}

.rider-tree-label {
	flex: 1;
	display: flex;
	align-items: center;
	height: 100%;
	line-height: 1.2;
}

.rider-tree-check {
	width: 40px;
	height: 40px;
	display: flex;
	justify-content: center;
	align-items: center;
}

.rider-tree-check-yes,
.rider-tree-check-no {
	width: 20px;
	height: 20px;
	border-top-left-radius: 20%;
	border-top-right-radius: 20%;
	border-bottom-right-radius: 20%;
	border-bottom-left-radius: 20%;
	border-top-width: 1rpx;
	border-left-width: 1rpx;
	border-bottom-width: 1rpx;
	border-right-width: 1rpx;
	border-style: solid;
	border-color: #007aff;
	display: flex;
	justify-content: center;
	align-items: center;
	box-sizing: border-box;
}

.rider-tree-check-yes-b {
	width: 12px;
	height: 12px;
	border-top-left-radius: 20%;
	border-top-right-radius: 20%;
	border-bottom-right-radius: 20%;
	border-bottom-left-radius: 20%;
	background-color: #007aff;
}

.rider-tree-check .radio {
	border-top-left-radius: 50%;
	border-top-right-radius: 50%;
	border-bottom-right-radius: 50%;
	border-bottom-left-radius: 50%;
}

.rider-tree-check .radio .rider-tree-check-yes-b {
	border-top-left-radius: 50%;
	border-top-right-radius: 50%;
	border-bottom-right-radius: 50%;
	border-bottom-left-radius: 50%;
}

.hover-c {
	opacity: 0.6;
}
</style>
